﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using Talk.Net.Library;

namespace Talk.Net
{
	class EncodingManager
	{

		private static byte[] ConvertToByte(sbyte[] input)
		{
			byte[] output = new byte[input.Length];
			for (int i = 0; i < input.Length; i++)
			{
				output[i] = (byte)((int)input[i] + 128);
			}
			return output;
		}

		private static short[] ConvertToShort(byte[] input)
		{
			short[] output = new short[input.Length / 2];

			for (int i = 0; i < input.Length / 2; i++)
			{
				output[i] = BitConverter.ToInt16(input, i * 2);
			}

			return output;
		}

		private static bool[] FewestBits(int Delta)
		{
			string bits = Convert.ToString(Delta, 2).PadLeft(8,'0');
			bool[] results = new bool[bits.Length];

			for (int i = 0; i < results.Length; i++)
			{
				if (bits[i] == '0')
				{
					results[i] = false;
				}
				else
				{
					results[i] = true;
				}
			}

			return results;
		}

		public static byte[] Compress2(byte[] content)
		{
			StringBuilder results = new StringBuilder();
			short[] samples = ConvertToShort(content);
			int[] deltas = new int[samples.Length - 1];
			int[] deltas2 = new int[samples.Length-2];

			int LastSample;
			int LastDelta;
			int Delta;
			List<int> Blocks = new List<int>();

			LastSample = samples[0];
			for (int i = 1; i < samples.Length; i++)
			{
				Delta = Math.Abs(LastSample - samples[i]);
				if (Blocks.Contains(Delta))
				{

				}
				else
				{
					Blocks.Add(Delta);
				}

				deltas[i-1] = Delta;
				LastSample = samples[i];
			}

			Blocks = new List<int>();

			LastDelta = deltas[0];
			for (int i = 1; i < deltas.Length; i++)
			{
				Delta = Math.Abs(LastDelta - deltas[i]);
				if (Blocks.Contains(Delta))
				{

				}
				else
				{
					Blocks.Add(Delta);
				}

				deltas2[i-1] = Delta;
				LastDelta = deltas[i];
			}

			return new byte[1];
		}

		public static byte[] Compress(byte[] content)
		{
			// my first compression algorithm for digital audio signals
			// it started to reach about 40% compression, as i researched these techniques
			// more i found that what i was attempting was called delta encoding

			// format
			// [D]	:	Delta				0/1		0=Non Compressed 16bit sample	1=Delta
			// [R]	:	Repeat			0/1		0=Non Repeat	1=Repeat Last Delta
			// [S]  :	Sign				0/1		0=-	1=+
			// [L]	: Length			0/1		0= 4bit	1=8bit
			// [P]	: Payload	
			//	0			[P=16]
			//	11		[P=2]
			//	1010	[P=4]
			//	1011	[P=8]

			short[] samples = ConvertToShort(content);
			short LastSample;
			short LastDelta;
			int Delta;
			List<int> deltas = new List<int>();
			StringBuilder results = new StringBuilder();
			Dictionary<int, int> sampleprofile = new Dictionary<int, int>();

			LastSample = samples[0];
			// *****************THIS IS A BUG WAITING TO SMURF!!!!!!!!!
			// What happens when the first delta value is 0?
			LastDelta = 0;

			for (int i = 1; i < samples.Length; i++)
			{
				Delta = LastSample - samples[i];

				if (sampleprofile.ContainsKey(Math.Abs(Delta)))
				{
					sampleprofile[Math.Abs(Delta)] = sampleprofile[Math.Abs(Delta)] + 1;
				}
				else
				{
					sampleprofile.Add(Math.Abs(Delta), 1);
				}

				if (Math.Abs(Delta) < 255)
				{
					// can be compressed, this is a delta modified value coming
					results.Append("1");

					// repeat last delta
					if (Delta == LastDelta)
					{
						results.Append("1");
						// done with this sample, now thats compression 16 bits to 2 bits
					}
					else
					{
						results.Append("0");

						// not a repeat of last, continue with data
						if (Delta < 0)
						{
							// is negative
							results.Append("0");
						}
						else
						{
							// is positive
							results.Append("1");
						}

						string bits;
						if (Math.Abs(Delta) < 16)
						{
							results.Append("0");
							bits = Convert.ToString(Math.Abs(Delta), 2).PadLeft(4, '0');
						}
						else
						{
							results.Append("1");
							bits = Convert.ToString(Math.Abs(Delta), 2).PadLeft(8, '0');
						}
						results.Append(bits);
					}
				}
				LastSample = samples[i];
			}

			string full = results.ToString();
			List<byte> bytes = new List<byte>();

			for (int i = 0; i < full.Length; i = i + 8)
			{
				if (i + 8 < full.Length)
				{
					bytes.Add(Convert.ToByte(full.Substring(i, 8), 2));
				}
				else
				{
					int remaining = full.Length - i;
					try
					{
						bytes.Add(Convert.ToByte(full.Substring(i, remaining).PadRight(8, '0'),2));
					}
					catch (Exception eios)
					{

					}
				}
			}

			return bytes.ToArray();
		}
	}
}
